package com.sdy.supermarket.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sdy.auth.client.service.SsoService;
import com.sdy.common.model.BizException;
import com.sdy.common.model.FileObj;
import com.sdy.common.model.Response;
import com.sdy.common.utils.Assert;
import com.sdy.common.utils.StringUtil;
import com.sdy.fs.api.FsApi;
import com.sdy.redis.service.RedisService;
import com.sdy.supermarket.biz.constants.RedisConstants;
import com.sdy.supermarket.biz.model.GsAppIpApply;
import com.sdy.supermarket.biz.model.GsNotice;
import com.sdy.supermarket.biz.model.GsRes;
import com.sdy.supermarket.biz.model.GsUserRes;
import com.sdy.supermarket.biz.service.GsResService;
import com.sdy.supermarket.biz.service.GsUserNoticeService;
import com.sdy.supermarket.biz.service.GsUserResService;
import com.sdy.supermarket.biz.service.IpApplyService;
import com.sdy.supermarket.biz.service.WorkbenchService;
import com.sdy.supermarket.biz.vo.ResSimpleVO;
import com.sdy.usercenter.api.UserQueryApi;
import com.sdy.usercenter.api.dto.UserDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工作台
 *
 * @author zhouziqiang
 */
@RestController
@Slf4j
@RequestMapping("/workbench")
public class WorkbenchController {
    @Autowired
    private IpApplyService ipApplyService;
    @Autowired
    private WorkbenchService workbenchService;
    @Autowired
    private SsoService ssoService;
    @Autowired
    private GsUserResService gsUserResService;
    @Autowired
    private GsResService gsResService;
    @Autowired
    private GsUserNoticeService gsUserNoticeService;
    @Autowired
    private RedisService redisService;
    @Autowired
    private FsApi fsApi;
    @Autowired
    private UserQueryApi userQueryApi;

    /**
     * 工作台基本信息
     */
    @GetMapping("/commonInfo")
    public Response commonInfo(HttpServletRequest request) throws Exception {
        Integer userId = ssoService.getUserId(request);
        UserDTO user = userQueryApi.getUser(userId);
        Map<String, Object> map = new HashMap<>(16);
        map.put("resCount", gsUserResService.listUserRes(user.getOwnDeptId()).size());
        // 未读消息
        List<GsNotice> unReadNotice = gsUserNoticeService.UnReadNotice(ssoService.getUserInfo(request).getUserId());
        map.put("unreadNoticeCount", unReadNotice.size());
        // 获取近七天的浏览量
        map.put("todayVisitCount", getViewsList(RedisConstants.REDIS_PREFIX_VIEWS));
        // 获取近七天得用户访问量数据
        map.put("todayUserCount", getViewsList(RedisConstants.REDIS_PREFIX_USER_VIEWS));
        // 获取近七天的应用接入数量
        List<GsRes> res7DaysList = gsResService.get7DaysList();
        // 把查询到的数据中的创建时间字段后面的详细时间切割掉，只剩下日期,方便分组
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        for (GsRes res : res7DaysList) {
            String date = simpleDateFormat.format(res.getCreateTime());
            Date parse = simpleDateFormat.parse(date);
            res.setCreateTime(parse);
        }
        Map<Date, List<GsRes>> collect = res7DaysList.stream().collect(Collectors.groupingBy(GsRes::getCreateTime));
        List<Map<String, Object>> totalUserCount = new ArrayList<>();
        for (Map.Entry<Date, List<GsRes>> entry : collect.entrySet()) {
            Map<String, Object> data = new HashMap<>();
            data.put("date", simpleDateFormat.format(entry.getKey()));
            data.put("data", entry.getValue().size());
            totalUserCount.add(data);
        }
        if (!totalUserCount.isEmpty() && totalUserCount.size() != 7) {
            for (int i = totalUserCount.size(); i <= 7; i++) {
                Map<String, Object> data = new HashMap<>();
                data.put("date", "emptyDate" + i);
                data.put("data", 0);
                totalUserCount.add(data);
            }
        }
        map.put("appJoinCount", totalUserCount);
        map.put("appJoin", gsResService.list().size());
        // 获取用户数量
        List<GsUserRes> userRes7DaysList = gsUserResService.get7DaysList();
        for (GsUserRes userRes : userRes7DaysList) {
            String date = simpleDateFormat.format(userRes.getCreateTime());
            Date parse = simpleDateFormat.parse(date);
            userRes.setCreateTime(parse);
        }
        Map<Date, List<GsUserRes>> collect1 = userRes7DaysList.stream().collect(Collectors.groupingBy(GsUserRes::getCreateTime));
        List<Map<String, Object>> appJoinCount = new ArrayList<>();
        for (Map.Entry<Date, List<GsUserRes>> entry : collect1.entrySet()) {
            Map<String, Object> data = new HashMap<>();
            data.put("date", simpleDateFormat.format(entry.getKey()));
            data.put("data", entry.getValue().size());
            appJoinCount.add(data);
        }
        if (!appJoinCount.isEmpty() && appJoinCount.size() != 7) {
            for (int i = appJoinCount.size(); i <= 7; i++) {
                Map<String, Object> data = new HashMap<>();
                data.put("date", "emptyDate" + i);
                data.put("data", 0);
                appJoinCount.add(data);
            }
        }
        map.put("totalUserCount", appJoinCount);
        map.put("totalUser", gsUserResService.list().size());
        return Response.success(map);
    }

    private List<Map<String, Object>> getViewsList(String keyPrefix) {
        List<Map<String, Object>> viewsList = new ArrayList<>();
        for (long i = 1; i <= 7; i++) {
            Map<String, Object> map = new HashMap<>();
            String key = keyPrefix + LocalDate.now().minusDays(i) + "";
            map.put("date", LocalDate.now().minusDays(i));
            Integer data = redisService.get(key, Integer.class);
            if (null != data) {
                map.put("data", data);
            } else {
                map.put("data", 0);
            }
            viewsList.add(map);
        }
        return viewsList;
    }


    /**
     * 我拥有的资源
     */
    @GetMapping("/myRes")
    public Response myRes(HttpServletRequest request, Boolean commonUse) {
        Integer userId = ssoService.getUserInfo(request).getUserId();
        UserDTO user = userQueryApi.getUser(userId);
        List<GsUserRes> userResList = gsUserResService.listUserRes(user.getOwnDeptId());
        List<FileObj> fileListInfo = fsApi.getFileListInfo(userResList.stream().map(userRes -> userRes.getGsRes().getIcon()).collect(Collectors.toList()));
        for (FileObj file : fileListInfo) {
            for (GsUserRes res : userResList) {
                if (res.getGsRes().getIcon().equals(file.getId())) {
                    res.getGsRes().setIconInfo(file);
                }
            }
        }
        List<ResSimpleVO> result = userResList
                .stream()
                .map(item -> ResSimpleVO.format(item.getGsRes()).setCommonUse(item.getCommonUse()))
                .collect(Collectors.toList());
        if (commonUse != null) {
            if (commonUse) {
                result = result.stream().filter(item -> item.getCommonUse().equals(1)).collect(Collectors.toList());
            } else {
                result = result.stream().filter(item -> item.getCommonUse().equals(0)).collect(Collectors.toList());
            }
        }
        return Response.success(result);
    }

    /**
     * 我拥有的资源 - 分页 + 参数查询
     */
    @GetMapping("/myResPage")
    public Response myResPage(HttpServletRequest request, String name, Integer state, Page<ResSimpleVO> page) throws UnsupportedEncodingException {
        Integer userId = ssoService.getUserInfo(request).getUserId();
        List<GsUserRes> userResList = gsUserResService.listUserRes(userId);
        name = URLDecoder.decode(name, "UTF-8");
        List<ResSimpleVO> result = userResList
                .stream()
                .map(item -> ResSimpleVO.format(item.getGsRes()))
                .collect(Collectors.toList());
        String finalName = name;
        result = result.stream()
                .filter(item -> StringUtil.isBlank(finalName) || item.getName().contains(finalName))
                .filter(item -> state == null || item.getState().equals(state))
                .collect(Collectors.toList());
        int start = (int) ((page.getCurrent() - 1) * page.getSize());
        int end = Math.min((int) (page.getCurrent() * page.getSize()), result.size());
        if (result.size() <= start) {
            result = new ArrayList<>();
        } else {
            result = result.subList(start, end);
        }
        result = result.subList(start, end);
        Page<ResSimpleVO> pageResult = new Page<ResSimpleVO>(page.getCurrent(), page.getSize()).setRecords(result);
        return Response.success(pageResult);
    }

    /**
     * 我没有拥有的资源
     */
    @GetMapping("/otherRes")
    public Response otherRes(HttpServletRequest request) {
        Integer userId = ssoService.getUserInfo(request).getUserId();
        List<GsUserRes> userResList = gsUserResService.listUserRes(userId);
        List<GsRes> otherResList;
        if (!userResList.isEmpty()) {
            otherResList = gsResService.list(new LambdaQueryWrapper<GsRes>()
                    .notIn(GsRes::getId, userResList
                            .stream()
                            .map(GsUserRes::getResId)
                            .collect(Collectors.toList())).eq(GsRes::getState, 1));
        } else {
            otherResList = gsResService.list(Wrappers.<GsRes>lambdaQuery().eq(GsRes::getState, 1));
        }
        if (!otherResList.isEmpty()) {
            List<FileObj> listInfo = fsApi.getFileListInfo(otherResList.stream().map(GsRes::getIcon).collect(Collectors.toList()));
            for (GsRes res : otherResList) {
                for (FileObj file : listInfo) {
                    if (res.getIcon().equals(file.getId())) {
                        res.setIconInfo(file);
                    }
                }
            }
        }
        List<ResSimpleVO> result = otherResList
                .stream()
                .map(ResSimpleVO::format)
                .collect(Collectors.toList());
        return Response.success(result);
    }

    /**
     * 设置常用应用
     *
     * @param resId 资源id
     * @param type  1-设置常用 0-取消常用
     */
    @PostMapping("/setCommonRes")
    public Response setCommonRes(HttpServletRequest request, Integer resId, Integer type) throws BizException {
        Integer userId = ssoService.getUserInfo(request).getUserId();
        Assert.isNull(resId, "资源id不能为空");
        Assert.isNull(type, "type不能为空");
        Assert.isTrue(!type.equals(0) && !type.equals(1), "type参数错误");
        gsUserResService.setCommonRes(userId, resId, type);
        return Response.success();
    }

    /**
     * 我的通知
     */
    @GetMapping("/myNoticePage")
    public Response myNoticePage(HttpServletRequest request, Page page) {
        return Response.success(workbenchService.userNoticePage(ssoService.getUserInfo(request).getUserId(), page));
    }

    /**
     * 自建系统ip申请单
     */
    @GetMapping("/app/ipApplyFormPage")
    public Response ipApplyFormPage(HttpServletRequest request,
                                    Page<GsAppIpApply> page,
                                    Integer state,
                                    String applyNo,
                                    String resName) throws UnsupportedEncodingException {
        resName = URLDecoder.decode(resName, "UTF-8");
        // TODO 校验用户权限
        return Response.success(ipApplyService.pageIpApply(page, state, applyNo, resName));
    }

    /**
     * 自建系统ip申请单详情
     */
    @GetMapping("/app/ipApplyFormDetail")
    public Response ipApplyFormDetail(HttpServletRequest request,
                                      String applyNo) {
        // TODO 校验用户权限
        return Response.success(ipApplyService.getIpApply(applyNo));
    }
}
